//
// Created by zken on 2024/12/2.
//
#include <iostream>

using namespace std;

#include "analyseRecord.h"
#include "util.h"
#include"FourthTuple.h"
#ifndef PROJECTLIZE_ATTRFORMAT_H
#define PROJECTLIZE_ATTRFORMAT_H


class ProductionConfig {
public:
    string left; // 左部策略
    vector<string> right; // 右部策略
    string facWork;

    string getRightString() {
        string res;
        for (const string &i: right) {
            res += i;
            res += " ";
        }
        return res;
    }

    ProductionConfig(const string &left, const vector<string> &right,
                     const string &facWork) : left(left), right(right), facWork(facWork) {}

    ProductionConfig() = default;

    ProductionConfig(const vector<string> &right, const string &left) : right(right), left(left) {}
};

class attrFormatTree {
private:
    // 文法器件
    ProductionUtil *productionUtil1;
    vector<ProductionConfig> pConfig;
    AstTreeNode *root;
    FourthTupleList tupleList;

public:
    void setProductionUtil1(ProductionUtil *productionUtil1);

    const vector<ProductionConfig> &getPConfig() const;

    AstTreeNode *getRoot() const;

    void setTupleList(const FourthTupleList &tupleList);

    FourthTupleList getTupleList()
    {
        return tupleList;
    }

public:
    /**
     * 属性文法的执行函数，根据传入的productionsName指定属性文法的策略
     * 使用配置文件进行，
     * 左部策略
     * 0，继承右部的某一个makeLeaf的点，然后处理左部
     * 1，此情况用于右侧为空，根据左部名字建立自己的leaf，然后传递给自己
     *
     * 右部策略
     * 0.be-children，作为儿子加入，如果是非终结符，则自动makeLeaf后加入
     * 1.不作为儿子加入
     * 2.MakeLeaf，建造叶子，作为父亲
     * 3.建造叶子，然后作为儿子加入
     * 4.直接作为父亲
     *
     * 以上处理的特点就是，不可以没有处理的非终结符号。
     * 如果没有设置父亲，那么默认使用策略4：
     * -对最左侧的非终结符直接作为父亲，
     * -对终结符，会直接抛出错误，不会主动makeleaf
     *
     * @param productionId 规约规则
     * @param values // 分析值
     * @return
     */
    AstTreeNode *doAttribute(int productionId, const vector<AnalyseValue> &values);

    /**
     * 建立四元组
     * @param productionId
     * @param values
     * @return
     */
     FourthTuple doAttributeFac(int productionId, const vector<AnalyseValue> &values);

    void readConfig(const string &filePath);

private :
    void readConfigLine(const string &line);

    string readConfigLineGetAttr(const string &s);

    /**
     * 建立叶子
     * @param value
     * @return
     */
    static AstTreeNode *makeLeaf(const AnalyseValue &value);

public:
    void showPConfig();

    void setRoot(AstTreeNode *node) {
        this->root = node;
    };

    void showAstTree();

    void showTreeNodesSupport(AstTreeNode *root, int depth);

    void showFac();

};


#endif //PROJECTLIZE_ATTRFORMAT_H
